package com.zyg.seckill.service.impl;

import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.zyg.common.entity.TbPayLog;
import com.zyg.common.utils.MyDate;
import com.zyg.seckill.dao.TbSeckillOrderMapper;
import com.zyg.seckill.entity.SeckillStatus;
import com.zyg.seckill.entity.StatusCode;
import com.zyg.seckill.entity.TbSeckillOrder;
import com.zyg.seckill.service.SeckillOrderService;
import com.zyg.seckill.service.impl.MultiThreadingCreateOrder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import java.util.Date;

@Service
public class SeckillOrderServiceImpl implements SeckillOrderService {

    @Autowired
    private StringRedisTemplate redisTemplate;
    @Autowired
    private MultiThreadingCreateOrder multiThreadingCreateOrder;
    @Autowired
    private TbSeckillOrderMapper orderMapper;


    // 保存秒杀商品
    @Override
    public TbSeckillOrder saveOrder(String username, Integer id) {
        //第一阶段：准备数据
        //1.1 得到当前的时间段
        String time = MyDate.getDateStr(MyDate.getDateMenus().get(0));
        //1.2 构造秒杀用户信息
        SeckillStatus seckillStatus = new SeckillStatus(username,new Date(),1,new Long(id),time);
        //1.3 将此用户放到redis中list集合的左边（redis中的队列: 左放右取）
        redisTemplate.boundListOps("seckillGoodsQueue").leftPush(JSON.toJSONString(seckillStatus));

        //第二阶段：避免重复排队
        //思想：以UserQueueCount为key，以登录名为小key，每次自增1，再判断，如果自增后的结果大于1，说明己经排过队了，此时，报异常
        Long count = redisTemplate.boundHashOps("UserQueueCount").increment(username, 1);
        if(count > 1){
            throw new RuntimeException(StatusCode.REPERROR + "");
        }

        //1.4 将用户信息备份到redis中，因为右侧弹出此用户后，就没有此用户的相关信息了
        redisTemplate.boundHashOps("UserQueueStatus").put(seckillStatus.getUsername(),JSON.toJSONString(seckillStatus));


        //第二阶段：异步下单
        return multiThreadingCreateOrder.syncCreateOrder();


    }

    //功能: 2. 根据登录名得到支付日志
    @Override
    public TbPayLog getPayLoyFromRedis(String username) {
        //2.1 得到日志的字符串形式
        String s = redisTemplate.opsForValue().get("seckill_paylog_" + username);
        //2.2 转换并返回 
        return JSON.parseObject(s,TbPayLog.class);
    }

   //功能: 3. 根据登录名得到订单
    @Override
    public TbSeckillOrder getOrderList(String loginName) {
        TbSeckillOrder seckillOrder = null;
        //3.1 得到订单的字符串形式
        String orderStr = (String) redisTemplate.boundHashOps("seckillOrder").get(loginName);
        //3.2 如果从redis中得不到,就从数据库中取
        if(StrUtil.isBlank(orderStr)){
            seckillOrder = orderMapper.selectOne(new QueryWrapper<TbSeckillOrder>().eq("user_id", loginName));
        }else{
            seckillOrder = JSON.parseObject(orderStr,TbSeckillOrder.class);
        }

        //3.2 返回
        return seckillOrder;
    }
}